#include "Game.h"
#include <QDebug>
#include <QSqlQuery>
#include <QSqlError>
#include <QTime>
#include "Server.h"
#include <QCoreApplication>
#include <QSettings>


Game::Game(QObject *parent) : QObject(parent)
{
    m_currStage  = Stoped;
    m_currRoundCursor  = 0;
    // TODO:m_setting
    m_lead  = Player_None;
    m_leadSelection  = 0;
}

Game::GameStage Game::stage() const
{
    return m_currStage;
}


QString Game::question() const{
    qDebug() << m_currRoundCursor << m_gameRounds.size();
    if(m_currRoundCursor && m_currRoundCursor <= m_gameRounds.size()){
        return m_gameRounds.at(m_currRoundCursor-1).question();
    }
    else{
        qDebug()  << "题目不可用";
        return QString();
    }
}


int Game::optionNumber() const{
    if(m_currRoundCursor && m_currRoundCursor <= m_gameRounds.size()){
        return m_gameRounds.at(m_currRoundCursor-1).optionNumber();
    }
    else{
        qDebug()  << "选项数量不可用";
        return 0;
    }
}


QString Game::optionAt(int index) const{
    if(m_currRoundCursor && m_currRoundCursor <= m_gameRounds.size()){
        return m_gameRounds.at(m_currRoundCursor-1).optionAt(index);
    }
    else{
        qDebug() << index << "索引处的选项不可用";
        return QString();
    }
}


int Game::rightSelectionIndex() const{
    qDebug() << "Right selection";
    qDebug() << "cursor" << m_currRoundCursor << "round size" << m_gameRounds.size();
    qDebug() << "right index" << m_gameRounds.at(m_currRoundCursor-1).rightOptionIndex();
    if(m_currRoundCursor && m_currRoundCursor <= m_gameRounds.size()){
        return m_gameRounds.at(m_currRoundCursor-1).rightOptionIndex();
    }
    else{
        qDebug() << "正确选项不可用";
        return -1;
    }
}


bool Game::hasNextRound() const{
    return (m_gameRounds.size()  &&  m_currRoundCursor < m_gameRounds.size());
}


bool Game::needNextPlayer() const
{
    return m_students.size() < m_setting.playerNumber();
}


GameSetting*  Game::setting() {
    return &m_setting;
}


int Game::correctNumberOf(quint32 playerId) const
{
    int count  = 0;
    foreach (const ScoreCell &cell, m_sheet) {
        if(cell.m_playerId == playerId  &&  cell.m_isCorrect ){
            count++;
        }
    }

    return count;
}



int Game::incorrectNumberOf(quint32 playerId) const
{
    int count  = 0;
    foreach (const ScoreCell &cell, m_sheet) {
        if(cell.m_playerId == playerId  &&  cell.m_isCorrect == false){
            count++;
        }
    }

    return count;
}

int Game::scoreOf(quint32 playerId) const
{
    int correctCnt  = 0;
    int incorrectCnt  = 0;
    foreach (const ScoreCell &cell, m_sheet) {
        if(cell.m_playerId == playerId ){
            if(cell.m_isCorrect){
                correctCnt++;
            }
            else{
                incorrectCnt++;
            }
        }
    }

    return correctCnt * 10 - incorrectCnt * 5;
}


int Game::selection() const
{
    return m_leadSelection;
}


bool Game::isCorrect() const
{
    return m_leadSelection == (rightSelectionIndex() + 1);
}


int Game::playerNumber() const
{
    return  m_students.size();
}


quint32 Game::playerIdAt(int index)
{
    Q_ASSERT(index < m_students.size());

    switch (index) {
    case 0:
        return Player_1;
    case 1:
        return Player_2;
    case 2:
        return Player_3;
    }
}


void Game::setGameSetting(GameSetting *setting){
    Q_ASSERT(setting != nullptr);

    qDebug() << setting->playerNumber() << setting->questionNumber() << setting->gameMode();
    m_setting.setPlayerNumber(setting->playerNumber());
    m_setting.setQuestionNumber(setting->questionNumber());
    m_setting.setGameMode(setting->gameMode());
}


bool Game::saveSetting(){
    QSettings config(QCoreApplication::applicationDirPath() + "/config.ini", QSettings::IniFormat);

    config.setValue("PlayerNumber", m_setting.playerNumber());
    config.setValue("GameMode", m_setting.gameMode());
    config.setValue("QuestionNumber", m_setting.questionNumber());


    return true;
}



void Game::beginGame(){          
    if(Stoped == m_currStage){

        qDebug() << "beginGame";

        //清空玩家
        m_students.clear();

        //清空分数
        m_sheet.clear();

        //复位round cursor
        m_gameRounds.clear();
        m_currRoundCursor  = 0;

        //随机生成答题列表
        generateGameRound();

        // 更新游戏状态
        m_currStage  = Started;

        //重置回答问题选手相关记录
        m_lead  = 0;
        m_leadSelection  = 0;

        emit askToReset();
    }
    else{
        qDebug() << "beginGame but current stage is not Stoped";
    }
}



void Game::endGame(){

    qDebug() << "endGame";

    emit askToReset();
    m_currStage  = Stoped;
}


void Game::roundNext(){
    qDebug() << "gameRound size" << m_gameRounds.size();
    qDebug() << "currRoundCursor" << m_currRoundCursor;
    //切换round
    if( m_currRoundCursor < m_gameRounds.size() ){
        m_currRoundCursor++;
        m_currStage  = PlayerReady;
        qDebug() << "Stage -> PlayerReady";

        m_lead  = 0;
        m_leadSelection  = 0;
    }
    else{
        qDebug("已经没有下一轮");
    }
}


void Game::readBracelet(quint32 player)
{
    emit askToReadBracelet(player);
}



void Game::beginCompete(){
    if(PlayerReady == m_currStage){
        emit askToCompete();

        m_currStage  = Competing;
        qDebug() << "Stage -> Competing";
    }
}

void Game::endCompete()
{
    emit askToReset();
}



void Game::validateCompetitor(quint32 player)
{
    if(Competing == m_currStage){
        if(m_setting.playerNumber() == 2  &&  player == Player_3){
            return;
        }

        m_lead  = player;

        qDebug() << player << "抢得答题权";
        emit competitorLocked(player);

        m_currStage  = Answering;
        qDebug() << "stage -> Answering";
    }
    else{
        qDebug() << "非抢答状态.当前游戏状态:" << m_currStage;
    }
}


// 处理选手的抢答请求
void Game::validateSelection(quint32 player, int selection)
{
    if( Answering == m_currStage &&  m_lead == player){        
        if(selection <= optionNumber()){
            m_leadSelection  = selection;

            qDebug() << "有人抢答" << player << selection;

            m_currStage  = Answered;
            qDebug() << "Stage -> Answered";

            emit validSelectionCommited(player, selection);

            decision();
        }
        else{
            qDebug() << "无效选择.共" << optionNumber() << "个选项，所选选项为" << selection;
        }
    }
    else{
        qDebug() << "无效答案提交。没有答题权！";
    }
}


// 某下位机读取到手环码
void Game::validatePlayer(quint32 player, QByteArray braceletSn)
{
    Q_UNUSED(player)

    qDebug() << "Validate player" << braceletSn;

    if(Started == m_currStage){
         Server::getInstance()->requestStudentId(braceletSn);
    }
}


void Game::fakePlayer(quint32 player, QByteArray braceletSn)
{

    onStudentRequestSuccess(braceletSn, player * 2);
}


// 手环码合法
void Game::onStudentRequestSuccess(const QString braceletSn,  qint64 studentId)
{
    m_students.append(studentId);

    if(m_students.size() == 1){
        emit playerJoin(Player_1);
    }
    else if(m_students.size() == 2){
        emit playerJoin(Player_2);

        if(m_setting.playerNumber() == 2){
            emit allPlayerReady();
        }
    }
    else if(m_students.size() == 3){
        emit playerJoin(Player_3);

        m_currStage  = PlayerReady;
        emit allPlayerReady();
    }
}


void Game::onStudentRequestFail(int error,const  QString errorString)
{
    Q_UNUSED(error)
    Q_UNUSED(errorString)

    if(m_students.size() == 0){
        emit playerIllegal(Player_1);
    }
    else if(m_students.size() == 1){
        emit playerIllegal(Player_2);
    }
    else {
        emit playerIllegal(Player_3);
    }
}



bool Game::loadRoundFromDatabase(){
    QSqlQuery query;
    bool ret  = query.exec("SELECT * from questions");
    if(ret == false){
        qDebug() << "数据库查询错误" << query.lastError().text();
        return false;
    }

    while(query.next()){
        char  rightOption  = query.value(6).toString().at(0).toLatin1();

        if(query.value(7).toInt() == 4){
            m_allRound.append(
                        Round(
                                  query.value(1).toString(),
                                  query.value(2).toString(),
                                  query.value(3).toString(),
                                  query.value(4).toString(),
                                  query.value(5).toString(),
                                  rightOption - 'A'
                                  )
                    );
        }
        else{
            m_allRound.append(
                        Round(
                                  query.value(1).toString(),
                                  query.value(2).toString(),
                                  query.value(3).toString(),
                                  query.value(4).toString(),
                                  rightOption - 'A'
                                  )
                    );
        }
    }


    m_flags  =  (unsigned char*)malloc( ( m_allRound.size() /8) + 1 );
    qDebug() << "Load round:" << m_allRound.size();
    return true;
}


bool Game::loadSetting()
{
    QSettings config(QCoreApplication::applicationDirPath() + "/config.ini", QSettings::IniFormat);

    int gameMode  = config.value("GameMode", 0).toInt();
    m_setting.setGameMode((GameSetting::GameMode)gameMode);

    int playerNumber  = config.value("PlayerNumber", 3).toInt();
    m_setting.setPlayerNumber(playerNumber);

    int questionNumber  = config.value("QuestionNumber", 20).toInt();
    m_setting.setQuestionNumber(questionNumber);

    //
    m_hardwareId  = config.value("HardwareSN", "unknown").toString();

    return true;
}


void Game::generateGameRound(){
    qDebug() << "开始生成随机问题列表";
    int needNum  = m_setting.questionNumber();
    int  max  = m_allRound.size();

    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));


    memset(m_flags, 0, max /8 + 1);

    while(needNum){
        int steps  = qrand() % (max - m_gameRounds.size() + 1);

        int count  = 0;

        for(int i = 0; i < max; i++){
            if( (m_flags[i/8] & (0x01 << (i%8)))  ==  0){
                count++;
                if(count == steps){
                    m_gameRounds.append(m_allRound.at(i));
                    m_flags[i/8]  |= (0x01 << (i%8));
                    needNum--;
                    break;
                }
            }
        }
    }

    qDebug() << "问题列表生成完毕";
}


// 每次回答一题，就对回答问题的选手进行分数判定并记录
void Game::decision()
{
    if(m_currStage == Answered)    {
        if(m_lead){
            if(m_leadSelection){
                m_sheet.append(ScoreCell(m_lead, rightSelectionIndex() == m_leadSelection -1) );
            }
            // Answer is right

            else{
                m_sheet.append(ScoreCell(m_lead, false));
            }
        }
    }

    foreach (const ScoreCell &cell, m_sheet) {
        qDebug() << cell.m_playerId << cell.m_isCorrect;
    }
}



void Game::pushScore()
{
   // Server::getInstance()->pushScore();
    for(int i = 0; i < m_students.size(); i++){
        qDebug() << "Push    score";
        Server::getInstance()->pushScore(m_hardwareId, m_students.at(i), scoreOf(playerIdAt(i)));
    }
}
